#include <iostream>
#include <functional>
#include <memory>
#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "Calculate.hpp"
#include "Log.hpp"

using namespace protocol_ns;

void Usage(char* proc)
{
    std::cout<<"Usage:\t"<<proc<<" serverport"<<std::endl;
}

//回调函数
using callback_t = std::function<Response(const Request& req)>;//计算函数

class Service
{
public:
    Service(callback_t cb)
    :_cb(cb)
    {}

    void ServiceHelper(socket_ptr sockptr,InetAddr client)
    {
        int sockfd = sockptr->SockFd();
        Log(DEBUG, "get a new link, info %s:%d, fd : %d\n", client.Ip().c_str(), client.Port(), sockfd);
        std::string clientaddr = "[" + client.Ip() + ":" + std::to_string(client.Port()) + "] ";
        std::string inbuffer;

        while(1)
        {
            sleep(5);

            Request req;

            int n = sockptr->Recv(&inbuffer);
            if(n<0)
            {
                Log(DEBUG, "client %s quit\n", clientaddr.c_str());
                break;
            }
            //读到的数据放在了inbuffer里面

            std::string package;
            while(1)
            {
                sleep(1);
                std::cout<<"inbuffer:"<<inbuffer<<std::endl;
                package = Decode(inbuffer);
                if(package.empty())
                {
                    break;
                }
                //说明读到了一个完整的json串
                std::cout << "------------------------begin---------------" << std::endl;
                std::cout << "resq string:\n"<< package << std::endl;
                
                //反序列化
                req.Deserialize(package);

                //函数回调
                Response resp = _cb(req);

                //创建一个string串，把resq的结果放进去
                std::string send_str;
                resp.Serialize(&send_str);

                //打印一下
                std::cout << "resp Serialize:" << std::endl;
                std::cout << send_str << std::endl;

                //编码一下，把报文前后缀放进去
                Decode(send_str);
                //打印一下
                std::cout << "resp Encode:" << std::endl;
                std::cout << send_str << std::endl;

                sockptr->Send(send_str);
            }

        }

    }

private:
    callback_t _cb;
};


int main(int argc,char* argv[])
{

    if(argc!=2)
    {
        Usage(argv[0]);
        exit(-1);
    }
    uint16_t serverport = std::stoi(argv[1]);

    //daemon(0, 0);//守护线程
    EnableFile();
    Calculate cal;

    Service calservice(std::bind(&Calculate::Excute,&cal,std::placeholders::_1));
    io_server_t service = std::bind(&Service::ServiceHelper,&calservice,std::placeholders::_1,std::placeholders::_2);
    std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>(serverport,service);
    tsvr->Loop();


    return 0;
}